﻿#include<iostream>
using namespace std;

//class Person {
//public:
//	//只有成员函数才可以加virtual
//	virtual void BuyTicket() //这里的virtual必须加，才可以构成重写
//	{
//		cout << "买票-全价" << endl;
//	}
//
//	//协变：返回类型必须是父子类的指针/引用
//	//virtual A* BuyTicket()
//	//{
//	//	cout << "买票-全价" << endl;
//	//	return nullptr;
//	//}
//};
//
//class Student : public Person {
//public:
//	//重写：派生类虚函数和基类虚函数的返回值、函数名、参数列表的类型完全相同
//	//这里的重写是重写函数的实现
//	//这里的派生类成员函数不加virtual就相当于用基类虚函数的声明加上自己函数的实现来构成重写
//	virtual void BuyTicket() //这里的virtual可加可不加都构成重写，建议加
//	{ 
//		cout << "买票-打折" << endl; 
//	}
//
//	//协变
//	/*virtual B* BuyTicket()
//	{
//		cout << "买票-打折" << endl;
//		return nullptr;
//	}*/
//};
//
//void Func(Person* ptr)//基类的指针/引用
//{
//	// 这⾥可以看到虽然都是Person指针Ptr在调⽤BuyTicket
//	// 但是跟ptr没关系，⽽是由ptr指向的对象决定的。
//
//	ptr->BuyTicket();//必须是基类的指针/引用指向虚函数
//}

//int main()
//{
//	Person ps;
//	Student st;
//	Func(&ps);
//	Func(&st);
//	return 0;
//}

//class A
//{
//public:
// //这里必须加virtual，在编译器将析构统一处理为destructor(),就构成多态，不加的话可能会造成内存泄漏
//	virtual ~A()//当一个类希望被继承是就将它的析构加virtual
//	{
//		cout << "~A()" << endl;
//	}
//};
//
//class B : public A {
//public:
//	~B()
//	{
//		cout << "~B()->delete:" << _p << endl;
//		delete _p;
//	}
//protected:
//	int* _p = new int[10];
//};
//
//void func(A* ptr)
//{
//	delete ptr;
// //多态的时候，就会将所有析构函数统一处理为destructor()
//	// ptr->destructor()     // 构成多态
//	// operator delete(ptr)
//}
//
//int main()
//{
//	/*A aa1;
//	B bb1;*/
//
//	/*func(new A);
//	func(new B);*/
//
//	A* p1 = new A;
//	A* p2 = new B;
//
//	delete p1;
//	delete p2;
//
//	return 0;
//}

class A
{
public:
	virtual void func(int val = 1) { std::cout << "A->" << val << std::endl; }
	virtual void test() { func(); }
};

class B : public A
{
public:
	//这道题就考的是派生类的成员函数不加virtual，对象会如何调用成员函数
	//这里加不加virtual，都是用基类虚函数的声明加上自己函数的实现来构成重写
	virtual void func(int val = 0) { std::cout << "B->" << val << std::endl; }
};

//int main(int argc, char* argv[])
//{
//	B* p = new B;
//	p->test();//这里是相当于是用基类成员的声明加派生类成员的定义来实现重写
//	p->func();
//	return 0;
//}


//class Car {
//public:
//	virtual void Dirve()
//	{}
//};
//class Car
//{
//public:
//	virtual void Drive() final {}//final修饰的基类虚函数，派生类就无法重写
//};
//class Benz : public Car 
//{
//public:
//	virtual void Drive() override//可以帮助用户检测是否重写
//	{ 
//		cout << "Benz-舒适" << endl; 
//	}
//};

//int main()
//{
//	Benz b;
//	b.Drive();
//	return 0;
//}

class Car//抽象类：无法实例化对象
{
public:
	virtual void Drive() = 0;//纯虚函数：一般不定义实现
};
class Benz :public Car
{
public:
	virtual void Drive()//必须重写，否则也是抽象类
	{
		cout << "Benz-舒适" << endl;
	}
};
class BMW :public Car
{
public:
	virtual void Drive()//必须重写，否则也是抽象类
	{
		cout << "BMW-操控" << endl;
	}
};

class Base
{
public:
	virtual void Func1()
	{
		cout << "Func1()" << endl;
	}

	virtual void Func2()
	{
		cout << "Func2()" << endl;
	}

	void Func3()
	{
		cout << "Func3()" << endl;
	}
protected:
	int _b = 1;
	char _ch = 'x';
};
//
//int main()
//{
//	Base b;//一个派生类实现多态后，就会含有一个虚函数表指针(32位下4个字节，64位下8个字节)
//	cout << sizeof(b) << endl;
//
//	return 0;
//}

class Person {
public:
	virtual void BuyTicket() { cout << "买票-全价" << endl; }
private:
	string _name;
};

class Student : public Person {
public:
	virtual void BuyTicket() { cout << "买票-打折" << endl; }
private:
	string _id;
};

class Soldier : public Person {
public:
	virtual void BuyTicket() { cout << "买票-优先" << endl; }
private:
	string _codename;
};

void Func(Person& ptr)
{
	// 这里可以看到虽然都是Person指针Ptr在调用BuyTicket
	// 但是跟ptr没关系，而是由ptr指向的对象决定的。
	ptr.BuyTicket();
}

int main()
{
	// 其次多态不仅仅发生在派生类对象之间，多个派生类继承基类，重写虚函数后
	// 多态也会发生在多个派生类之间。
	Person ps;
	Student st;
	Soldier sr;

	Func(ps);
	Func(st);
	Func(sr);

	return 0;
}
